package com.jwgf.report;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Set;
import java.util.TreeSet;

import com.jwgf.common.AppContext;
import com.jwgf.smarowindingmachine_unity.R;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.util.Log;

public class ShiftTimeRule {

    private static final String SHIFT_NUM = "shift_num";//班次
    private static final String START_TIME = "start_time";
    private static final String END_TIME = "end_time";
    private static final String ACTUAL_START_TIME = "actual_start_time";
    private static final String OPERATOR = "operator";
    private static final String SHIFT_TEAM = "shift_team";

    private static ShiftTimeRule instance = new ShiftTimeRule();
    private DayInfo[] dayInfoArray = new DayInfo[7];
    private SharedPreferences sp = AppContext.getInstance().getSharedPreferences("shift_settings",
            Context.MODE_PRIVATE);

    private ShiftTimeRule() {
        loadSettings();
    }

    public static ShiftTimeRule getInstance() {
        return instance;
    }

    public boolean smartSetting(DayInfo info) {
        if (info.checkValid()) {
            for (int i = 0; i < dayInfoArray.length; ++i) {
                dayInfoArray[i] = info;
            }
            saveSettings();
            updateTimeRange();
            return true;
        } else {
            loadSettings();
            return false;
        }
    }

    public boolean normalSetting(int dayofWeek, DayInfo info) {
        if (info.checkValid()) {
            dayInfoArray[dayofWeek - 1] = info;
            for (int i = 0; i < dayInfoArray.length; ++i) {
                dayInfoArray[i].setShiftInfo(0, info.getShiftInfo(0));
                if (!dayInfoArray[i].checkValid()) {
                    loadSettings();
                    return false;
                }
            }
            saveSettings();
            updateTimeRange();
            return true;
        } else {
            loadSettings();
            return false;
        }
    }

    public DayInfo getDayInfo(int dayofWeek) {
        return dayInfoArray[dayofWeek - 1];
    }

    public String getCurrentShiftNum() {
        int num = sp.getInt(SHIFT_NUM, 0);
        return String.valueOf(num);
    }

    public String getCurrentShiftActualStartTime() {
        if (sp.contains(ACTUAL_START_TIME)) {
            long ticks = 0;
            ticks = sp.getLong(ACTUAL_START_TIME, 0);
            Calendar startTime = Calendar.getInstance();
            startTime.setTimeInMillis(ticks);
            return String.valueOf(startTime.getTimeInMillis());
        } else {
            return String.valueOf(Calendar.getInstance().getTimeInMillis());
        }
    }

    public String getCurrentShiftStartTime() {
        if (sp.contains(START_TIME)) {
            long ticks = 0;
            ticks = sp.getLong(START_TIME, 0);
            Calendar startTime = Calendar.getInstance();
            startTime.setTimeInMillis(ticks);
            return String.valueOf(startTime.getTimeInMillis());
        } else {
            Calendar calendar = Calendar.getInstance();
            ArrayList<ShiftInfo> timeRange = getTimeRange(calendar);
            return String.valueOf(timeRange.get(0).getTime().getTimeInMillis());
        }
    }

    public String getCurrentShiftEndTime() {
        if (sp.contains(END_TIME)) {
            long ticks = 0;
            ticks = sp.getLong(END_TIME, 0);
            Calendar endTime = Calendar.getInstance();
            endTime.setTimeInMillis(ticks);
            return String.valueOf(endTime.getTimeInMillis());
        } else {
            Calendar calendar = Calendar.getInstance();
            ArrayList<ShiftInfo> timeRange = getTimeRange(calendar);
            return String.valueOf(timeRange.get(1).getTime().getTimeInMillis());
        }
    }

    public boolean isShiftChanged() {
        if (!sp.contains(START_TIME) || !sp.contains(END_TIME)) {
            updateTimeRange();
            return false;
        } else {
            Calendar start = Calendar.getInstance();
            Calendar end = Calendar.getInstance();
            start.setTimeInMillis(sp.getLong(START_TIME, 0));
            end.setTimeInMillis(sp.getLong(END_TIME, 0));
            Calendar cur = Calendar.getInstance();
//            Date dateStart = new Date(start.getTimeInMillis());
//            Date dateEnd = new Date(end.getTimeInMillis());
//            Date curTime = new Date(cur.getTimeInMillis());
//            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//            Log.i("isShiftChanged", "start:" + df.format(dateStart));
//            Log.i("isShiftChanged", "end:" + df.format(dateEnd));
//            Log.i("isShiftChanged", "cur:" + df.format(curTime));
            if (cur.after(start) && cur.before(end)) {
                return false;
            } else {
                return true;
            }
        }

    }

    public void updateTimeRange() {
        Calendar calendar = Calendar.getInstance();
        ArrayList<ShiftInfo> timeRange = getTimeRange(calendar);
        Editor edit = sp.edit();
        edit.putInt(SHIFT_NUM, timeRange.get(0).getNum());
        edit.putLong(START_TIME, timeRange.get(0).getTime().getTimeInMillis());
        edit.putLong(END_TIME, timeRange.get(1).getTime().getTimeInMillis());
        edit.putLong(ACTUAL_START_TIME, calendar.getTimeInMillis());
        edit.commit();
    }

    public long getNextStartTime() {
        Calendar nextStart = Calendar.getInstance();
        nextStart.setTimeInMillis(sp.getLong(END_TIME, 0));
        return nextStart.getTimeInMillis();
    }

    public String getOperator() {
        return sp.getString(OPERATOR, "Administrator");
    }

    public void setOperator(String operator) {
        sp.edit().putString(OPERATOR, operator).commit();
    }

    public String getShiftTeam() {
        return sp.getString(SHIFT_TEAM, AppContext.getInstance().getString(R.string.team_default));
    }


    public void setShiftTeam(String shiftTeam) {
        sp.edit().putString(SHIFT_TEAM, shiftTeam).commit();
    }

    private ArrayList<ShiftInfo> getTimeRange(Calendar cur) {
        ArrayList<ShiftInfo> timeRange = new ArrayList<ShiftInfo>();
        ArrayList<ShiftInfo> bigRangeList = getShiftInfoList(cur, -1);
        bigRangeList.addAll(getShiftInfoList(cur, 0));
        bigRangeList.addAll(getShiftInfoList(cur, 1));

        Log.i("ShiftInfo", new ShiftInfo(1, cur).toString());
        for (ShiftInfo info : bigRangeList) {
            Log.i("ShiftInfo", info.toString());

        }

        for (int i = 1; i < bigRangeList.size(); ++i) {

            if (cur.before(bigRangeList.get(i).getTime())) {
                timeRange.add(bigRangeList.get(i - 1));
                timeRange.add(bigRangeList.get(i));
                break;
            }
        }
        return timeRange;
    }

    private ArrayList<ShiftInfo> getShiftInfoList(Calendar cur, int dayOffset) {
        ArrayList<ShiftInfo> shiftInfoList = new ArrayList<ShiftInfo>();
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(cur.getTimeInMillis());
        calendar.add(Calendar.DAY_OF_MONTH, dayOffset);
        int dayofWeek = calendar.get(Calendar.DAY_OF_WEEK);
        ArrayList<ShiftInfo> curInfoList = dayInfoArray[dayofWeek - 1].getValidShiftInfo();
        for (int i = 0; i < curInfoList.size(); ++i) {
            int year = calendar.get(Calendar.YEAR);
            int month = calendar.get(Calendar.MONTH);
            int day = calendar.get(Calendar.DAY_OF_MONTH);
            int hour = curInfoList.get(i).getHour();
            int minute = curInfoList.get(i).getMinute();
            int second = 0;
            Calendar date = Calendar.getInstance();
//			date.add(Calendar.DAY_OF_MONTH, dayOffset);
            date.set(year, month, day, hour, minute, second);
            date.set(Calendar.MILLISECOND, 0);
            if (i > 0) {
                if (curInfoList.get(i).getTotalMinutes() < curInfoList.get(i - 1).getTotalMinutes()) {
                    date.add(Calendar.DAY_OF_MONTH, 1);
                }
            }
            int shiftNum = curInfoList.get(i).getNum();
            shiftInfoList.add(new ShiftInfo(shiftNum, date));
        }

        return shiftInfoList;
    }

    private ShiftInfo parseShift(String str) {
        String[] temp = str.split(",");
        int num = Integer.valueOf(temp[1]);
        int hour = Integer.valueOf(temp[2]);
        int minute = Integer.valueOf(temp[3]);
        return new ShiftInfo(num, hour, minute);
    }

    private int parseOrder(String str) {
        String[] temp = str.split(",");
        int order = Integer.valueOf(temp[0]);
        return order;
    }

    private void loadSettings() {
        for (int i = Calendar.SUNDAY; i <= Calendar.SATURDAY; ++i) {
            loadDayInfo(i);
        }
    }

    private void saveSettings() {
        for (int i = Calendar.SUNDAY; i <= Calendar.SATURDAY; ++i) {
            saveDayInfo(i);
        }
    }

    private void loadDayInfo(int dayofWeek) {
        TreeSet<String> defValues = new TreeSet<String>();
        defValues.add("0,1,8,00");
        defValues.add("1,2,14,00");
        defValues.add("2,3,20,00");
        defValues.add("3,4,2,00");
        Set<String> set = sp.getStringSet(String.valueOf(dayofWeek), defValues);
        if (dayInfoArray[dayofWeek - 1] == null) {
            dayInfoArray[dayofWeek - 1] = new DayInfo();
        }
        for (String str : set) {
            dayInfoArray[dayofWeek - 1].setShiftInfo(parseOrder(str), parseShift(str));
        }
    }

    private void saveDayInfo(int dayofWeek) {
        Editor edit = sp.edit();
        TreeSet<String> values = new TreeSet<String>();
        values.add("0," + dayInfoArray[dayofWeek - 1].getShiftInfo(0).toString());
        values.add("1," + dayInfoArray[dayofWeek - 1].getShiftInfo(1).toString());
        values.add("2," + dayInfoArray[dayofWeek - 1].getShiftInfo(2).toString());
        values.add("3," + dayInfoArray[dayofWeek - 1].getShiftInfo(3).toString());
        edit.putStringSet(String.valueOf(dayofWeek), values);
        edit.commit();
    }

}
